package cn.echase.ecare.yinfayun.service.impl;

import cn.echase.common.core.enums.ResultCode;
import cn.echase.ecare.common.mybatis.service.BaseService;
import cn.echase.ecare.yinfayun.domain.dto.OrgTransactionRecordDto;
import cn.echase.ecare.yinfayun.domain.entity.OrgTransactionRecord;
import cn.echase.ecare.yinfayun.domain.mapper.OrgTransactionRecordMapper;
import cn.echase.ecare.yinfayun.domain.vo.OrgTransactionRecordVo;
import cn.echase.ecare.yinfayun.service.IOrgTransactionRecordService;
import cn.echase.ecare.yinfayun.utils.ComparaUtils;
import cn.echase.ecare.yinfayun.utils.DateV3Util;
import cn.echase.ecare.yinfayun.utils.IncrementerUtils;
import cn.echase.ecare.yinfayun.utils.UcExcelUtils;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.tenant.helper.TenantHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static cn.echase.ecare.yinfayun.constants.YFYConstant.*;

/**
 * <p>
 * 机构交易记录 服务类
 * </p>
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrgTransactionRecordServiceImpl extends BaseService implements IOrgTransactionRecordService {

    @Resource
    private OrgTransactionRecordMapper baseMapper;

    @NotNull
    private LambdaQueryWrapper<OrgTransactionRecord> getOrgTransactionRecordLambdaQueryWrapper(OrgTransactionRecordDto orgTransactionRecord) {
        LambdaQueryWrapper<OrgTransactionRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrgTransactionRecord::getDelFlag, UN_DELETED);
        wrapper.eq(StringUtils.isNotEmpty(orgTransactionRecord.getTenantId()), OrgTransactionRecord::getTenantId, orgTransactionRecord.getTenantId());
        wrapper.eq(orgTransactionRecord.getAccountCategory() != null, OrgTransactionRecord::getAccountCategory, orgTransactionRecord.getAccountCategory());
        wrapper.eq(orgTransactionRecord.getTransactionType() != null, OrgTransactionRecord::getTransactionType, orgTransactionRecord.getTransactionType());
        wrapper.eq(orgTransactionRecord.getPayType() != null, OrgTransactionRecord::getPayType, orgTransactionRecord.getPayType());
        wrapper.like(StringUtils.isNotEmpty(orgTransactionRecord.getPayerName()), OrgTransactionRecord::getPayerName, orgTransactionRecord.getPayerName());
        if (orgTransactionRecord.getStartTime() != null && orgTransactionRecord.getEndTime()!=null) {
            orgTransactionRecord.setStartDateTime(DateV3Util.transDateToDate(orgTransactionRecord.getStartTime(), DATE_PATTERN_YYYY_MM_DD_000000));
            orgTransactionRecord.setEndDateTime(DateV3Util.transDateToDate(orgTransactionRecord.getEndTime(), DATE_PATTERN_YYYY_MM_DD_235959));
            wrapper.between(OrgTransactionRecord::getTransactionTime, orgTransactionRecord.getStartDateTime(), orgTransactionRecord.getEndDateTime());
        }
        wrapper.orderByDesc(OrgTransactionRecord::getTransactionTime);
        wrapper.orderByDesc(OrgTransactionRecord::getId);
        return wrapper;
    }

    @Override
    public JSONObject page(OrgTransactionRecordDto orgTransactionRecord) {
        LambdaQueryWrapper<OrgTransactionRecord> wrapper = this.getOrgTransactionRecordLambdaQueryWrapper(orgTransactionRecord);
        Page<OrgTransactionRecord> page = new Page<>(orgTransactionRecord.getPageNum(), orgTransactionRecord.getPageSize());
        Page<OrgTransactionRecordVo> orgTransactionRecordVoPage = baseMapper.selectVoPage(page, wrapper, OrgTransactionRecordVo.class);
        TableDataInfo<OrgTransactionRecordVo> tableDataInfo = this.getDataTable(ResultCode.SUCCESS.getCode(), orgTransactionRecordVoPage);
        List<OrgTransactionRecordVo> data = new ArrayList<>();
        for (OrgTransactionRecordVo transactionRecordVo : tableDataInfo.getRows()) {
            //TODO 获取长者床位信息
//            RemoteElderInfoVo eldInfo = this.getElderInfo(transactionRecordVo.getPayerId());
//            transactionRecordVo.setBedName(eldInfo == null ? null : eldInfo.getBedName());
            data.add(transactionRecordVo);
        }

        /*
         * 排序
         */
        Comparator<OrgTransactionRecordVo> comparator = new ComparaUtils<OrgTransactionRecordVo>().buildComparator(orgTransactionRecord.getSortDescList(),OrgTransactionRecordVo.class);
        if (comparator != null) {
            data = data.stream().sorted(comparator).collect(Collectors.toList());
        }
        tableDataInfo.setRows(data);

        JSONObject jsonObject = new JSONObject();
        jsonObject.set("page", tableDataInfo);

        orgTransactionRecord.setTransactionType(1);
        Long incomeAmount = TenantHelper.ignore(()-> baseMapper.getTotalAmount(orgTransactionRecord));
        jsonObject.set("incomeAmount", incomeAmount);

        orgTransactionRecord.setTransactionType(2);
        Long expensesAmount = TenantHelper.ignore(()-> baseMapper.getTotalAmount(orgTransactionRecord));
        jsonObject.set("expensesAmount", expensesAmount);
        return jsonObject;
    }

    /**
     * TODO 获取长者信息
     * */
//    public RemoteElderInfoVo getElderInfo(String payerId) {
//        RemoteElderInfoBo remoteElderInfoBo = new RemoteElderInfoBo();
//        remoteElderInfoBo.setUcId(payerId);
//        return remoteElderService.getElderInfo(remoteElderInfoBo);
//    }

    @Override
    public List<OrgTransactionRecordVo> list(OrgTransactionRecordDto orgTransactionRecord) {
        LambdaQueryWrapper<OrgTransactionRecord> wrapper = this.getOrgTransactionRecordLambdaQueryWrapper(orgTransactionRecord);
        List<OrgTransactionRecordVo> orgTransactionRecordVos = baseMapper.selectVoList(wrapper);
        for (OrgTransactionRecordVo transactionRecordVo : orgTransactionRecordVos) {
            //TODO 获取长者床位信息
//            RemoteElderInfoVo eldInfo = this.getElderInfo(transactionRecordVo.getPayerId());
//            transactionRecordVo.setBedName(eldInfo == null ? null : eldInfo.getBedName());
        }
        return orgTransactionRecordVos;
    }

    @Override
    public void export(HttpServletResponse httpServletResponse, OrgTransactionRecordDto orgTransactionRecord) {
        // 表格一数据
        List<String[]> oneList = new ArrayList<>();
        List<List<String[]>> dataLists = new ArrayList<>();

        String[] headers = {"序号", "长者姓名", "床位号", "收/支","科目类别","支付方式","说明","金额","交易时间","当前钱包余额"};
        oneList.add(headers);

        IncrementerUtils incrementer = new IncrementerUtils();
        List<OrgTransactionRecordVo> list = this.list(orgTransactionRecord);
        for (OrgTransactionRecordVo record : list) {
            String remark = record.getRemark();
            String payType = record.getPayType();
            String bedName = record.getBedName();
            String payerName = record.getPayerName();
            Integer changeMoney = record.getChangeMoney();
            Integer afterBalance = record.getAfterBalance();
            Date transactionTime = record.getTransactionTime();
            Integer transactionType = record.getTransactionType();
            Integer accountCategory = record.getAccountCategory();

            String payTypeStr = this.getPayTypeStr(payType);
            String changeMoneyStr = this.getChangeMoneyStr(changeMoney);
            String afterBalanceStr = this.getAfterBalanceStr(afterBalance);
            String transactionTypeStr = this.getTransactionTypeStr(transactionType);
            String accountCategoryStr = this.getAccountCategoryStr(accountCategory);

            String[] valueStrArr = new String[]{
                    incrementer.getIncrementedValue().toString(),
                    payerName,
                    bedName,
                    transactionTypeStr,
                    accountCategoryStr,
                    payTypeStr,
                    remark,
                    changeMoneyStr,
                    DateV3Util.format(transactionTime, DATE_PATTERN_YYYY_MM_DD_HH_MM_SS),
                    afterBalanceStr
            };
            oneList.add(valueStrArr);
        }

        // 多个表格导出就是多个sheet
        dataLists.add(oneList);
        UcExcelUtils ucExcelUtils = UcExcelUtils.initialization(dataLists, new String[]{"Sheet1"},null, httpServletResponse, "收支记录", null);
        // 执行导出
        ucExcelUtils.exportForExcelsOptimize(false);
    }

    @NotNull
    private String getPayTypeStr(String payType) {
        String payTypeStr="";
        if (payType != null){
            switch (payType) {
                case "cash" : payTypeStr = "现金"; break;
                case "mb_bdb" : payTypeStr = "掌银"; break;
                case "pos" : payTypeStr = "POS支付(农行)"; break;
                case "commonPos" : payTypeStr = "普通POS支付"; break;
                case "transfer" : payTypeStr = "转账"; break;
                case "wx" : payTypeStr = "微信"; break;
                case "balance" : payTypeStr = "预交金"; break;
                case "StaticQRCode" : payTypeStr = "静态码聚合支付"; break;
                case "deposit" : payTypeStr = "押金"; break;
                case "bmp" : payTypeStr = "扫码支付"; break;
                case "scan" : payTypeStr = "扫码支付"; break;
                default:break;
            }
        }

        return payTypeStr;
    }

    @NotNull
    private String getAccountCategoryStr(Integer accountCategory) {
        String acountCategoryStr="";
        if (accountCategory != null){
            switch (accountCategory) {
                case 1 : acountCategoryStr = "预收款"; break;
                case 2 : acountCategoryStr = "收入"; break;
                case 3 : acountCategoryStr = "支出"; break;
                default:break;
            }
        }

        return acountCategoryStr;
    }

    @NotNull
    private String getTransactionTypeStr(Integer transactionType) {
        String transactionTypeStr="";
        if (transactionType != null){
            switch (transactionType) {
                case 1 : transactionTypeStr = "收入"; break;
                case 2 : transactionTypeStr = "支出"; break;
                default:break;
            }
        }

        return transactionTypeStr;
    }

    @NotNull
    private String getMoneyStr(Integer money) {
        DecimalFormat decimalFormat = new DecimalFormat("###.00");
        String moneyStr="";
        if (money != null){
            moneyStr=  decimalFormat.format(money / 100.0);
        }

        return moneyStr;
    }

    @NotNull
    private String getChangeMoneyStr(Integer changeMoney) {
        return getMoneyStr(changeMoney);
    }

    @NotNull
    private String getAfterBalanceStr(Integer afterBalance) {
        return getMoneyStr(afterBalance);
    }

}
